Eureka: Service Discovery Clients

👉 Complete tutorial on registering microservices with Eureka Name server.

👉 Complying with best practices and security recommendations.


Microservice as Eureka clients

A Eureka Client is any microservice that registers itself with the Eureka Naming Server to become discoverable by other services.

By registering, the service provides it’s metadata (name, IP, port) and maintains a “heartbeat” to signal that it is alive and ready to handle traffic.

To enable discovery in a Spring Boot service, we need to include the client-side discovery dependency.

Maven dependency

Add the following starter to your microservice’s pom.xml. It adds the capability for both, Registration (acting as an instance) and Discovery (acting as a client to find others).

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

Enabling service discovery

To activate the discovery client, you annotate your main application class. While modern Spring Cloud versions (since 1.4+) often enable this automatically if the JAR is on the classpath, using the annotation is a best practice for clarity.

Use @EnableDiscoveryClient or @EnableEurekaClient.

@SpringBootApplication
@EnableDiscoveryClient
public class ProductServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductServiceApplication.class, args);
    }
}

Insight:
→ Use @EnableDiscoveryClient for Generic annotation / Vendor neutrality.
→ Use @EnableEurekaClient only if you want to strictly bind your code to Netflix Eureka.

@EnableEurekaClient@EnableDiscoveryClient
Enables service registration and discovery only with Eureka.More generic, works with multiple service registries.
It supports only Netflix Eureka.It supports Eureka, Consul, Zookeeper, etc.
It’s a concrete implementation.It’s an interface or contract.
It needs the spring-cloud-starter-netflix-eureka-client dependency to work.It’s a part of Spring Cloud dependencies. No specific dependency is needed.

Client configuration

The client needs to know the location of the Naming Server. This is defined in the application config file - application.yml or application.properties.

spring:
  application:
    name: product-service # Mandatory, This becomes the Service ID in Eureka

server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://eureka-host:8761/eureka/  # Eureka Server
  instance:
    prefer-ip-address: true # Recommended for Docker/Cloud environments

Insight:
eureka.instance.prefer-ip-address: If set to true, Eureka registers the IP of the service, instead of the hostname (more reliable in virtual networks eg. K8s).


Request flow

sequenceDiagram
    participant B as Microservice B (Provider)
    participant E as Eureka Server
    participant A as Microservice A (Consumer)

    Note over B,E: 1. Registration Phase
    B->>E: POST /eureka/apps/SERVICE-B (IP, Port, Metadata)
    E-->>B: 204 No Content (Registered)

    Note over B,E: 2. Health Monitoring
    loop Every 30 Seconds
        B->>E: PUT /eureka/apps/SERVICE-B (Heartbeat)
        E-->>B: 200 OK
    end

    Note over A,E: 3. Discovery Phase
    A->>E: GET /eureka/apps (Fetch Registry)
    E-->>A: 200 OK (JSON/XML List of all Services)
    Note right of A: A caches registry locally

    Note over A,B: 4. Service Consumption
    A->>A: Client-side Load Balance (Select Instance of B)
    A->>B: GET /api/data (Direct Call)
    B-->>A: 200 OK (Response)

    Note over E,B: 5. Eviction (If Heartbeat Fails)
    Note right of E: After 90s of no heartbeats...
    E->>E: Remove B from Registry

Health checks & Actuator

By default, Eureka determines a service’s status via a simple Heartbeat (is the application process running?). This can be misleading; as a service might be “alive” but could be “broken”, if its database or message broker is down.

By enabling Actuator Health checks, Eureka shifts from a passive heartbeat to an active health probe. It will only mark a service as UP if all internal health indicators (database, disk space, custom checks) are also GREEN.

To implement this, include the Actuator dependency and enable the Eureka health check bridge.

Maven dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Application configuration

eureka:
  client:
    healthcheck:
      enabled: true # Propagates Actuator status to Eureka
      
management:
  endpoints:
    web:
      exposure:
        include: "health" # Ensures the /health endpoint is available
  endpoint:
    health:
      show-details: always # Optional: useful for debugging

Heartbeat vs. Health check

FeatureDefault HeartbeatActuator Health Check
Detection LevelProcess/Network level.Application/Dependency level.
LogicI am still standing.I am ready to process traffic.
Failure ScenarioOnly marks DOWN if the app crashes.Marks OUT_OF_SERVICE if internal dependent services status eg. Database, Message Broker etc. is unhealthy.
Best ForDevelopment / Simple apps.Production / Mission-critical apps.

Note:
→ When health checks are enabled, if a service’s database goes down, its status in the Eureka dashboard will change from UP to OUT_OF_SERVICE.
→ This automatically stops Ribbon or LoadBalancer from routing traffic to that specific instance.


Best Practices for Credentials

In PROD grade applications, credentials are never hardcode. We use one of the following strategies to inject credentials safely.

→ Environment Variables

Inject the username and password from your CI/CD pipeline or container orchestrator (like Kubernetes Secrets).

eureka:
  client:
    service-url:
      defaultZone: http://${EUREKA_USER}:${EUREKA_PASSWORD}@eureka-server:8761/eureka/

→ Spring Cloud Vault / Config Server

When using HashiCorp Vault, Spring can fetch the credentials at startup and resolve the placeholders dynamically. This allows for secret rotation without redeploying code.

→ Placeholder Resolution

We can separate the credentials from the URL structure to make the config more readable:

eureka:
  client:
    service-url:
      defaultZone: http://admin:${eureka.password}@eureka-server:8761/eureka/

Security hardening checklist

PracticeWhy it’s necessary
Always Use HTTPSBasic Auth sends credentials as Base64 encoded strings; without SSL/TLS, they are easily intercepted.
Disable CSRFEureka clients send POST and PUT requests. Disable CSRF for the /eureka/** path on the server.
Network IsolationKeep the Eureka server on an internal VPC or private subnet. It should never be accessible from the public internet.
Separate Admin UsersUse different credentials for the Dashboard (human users) and the Service Registry (automated clients).
IP WhitelistingIf possible, restrict access to the Eureka server to specific IP ranges (e.g., your Kubernetes pod CIDR).

Security Levels summary

MethodSecurity LevelComplexityBest For…
No Auth🔴 LowNoneLocal development only.
Basic Auth🟡 MediumLowSmall-to-medium clusters via HTTPS.
Basic + Vault🟢 HighMediumEnterprise apps needing secret rotation.
mTLS (Certs)🟣 MaximumHighHigh-security environments (Finance/Gov).

Self-Registration Lifecycle

PhaseDescriptionDefault Interval
RegistrationOn startup, the client sends a POST request with its metadata.Once on app boot
HeartbeatThe client sends a PUT request to renew its leaseEvery 30 seconds (default)
Fetch RegistryThe client downloads the local cache of other services so it can call them even if Eureka goes down momentarily.Every 30 seconds